﻿using System;
using System.Drawing;
using System.Collections.Generic;

using Noris.Tools.TraceVisualiser.Support;

namespace Noris.Tools.TraceVisualiser.Components
{
	#region INTERFACE IDataSource : obecný datový zdroj
	/// <summary>
	/// Interface, definující obecný datový zdroj.
	/// Datový zdroj je objekt, který obsahuje metody specifikované v tomto interface.
	/// Metody jsou volány z grafické komponenty, v případě kdy komponenta potřebuje data k zobrazování, nebo kdy komponenta ukládá data.
	/// </summary>
    public interface IDataSource : IDisposable
	{
		/// <summary>
		/// Vlastnosti datového zdroje. Jde o statické informace.
		/// </summary>
		DataSourceProperties Properties { get; }
		/// <summary>
		/// Zde datový zdroj deklaruje, jaké grafy chce zobrazit.
		/// Vizuální vrstva deklarace převezme a založí odpovídající grafy, a naváže do nich tento datový zdroj.
		/// </summary>
		List<GraphDeclarationCls> GraphDeclarations { get; }
		/// <summary>
        /// Vstupní metoda, skrze kterou je datový zdroj požádán o zpracování požadavku.
        /// Požadavek může nést různá data, a může vracet různá data.
        /// Tato metoda je volána v asynchronním threadu (na pozadí), datový zdroj nijak neřeší threading.
        /// Synchronizaci práce datového zdroje a grafu řeší někdo jiný (AsyncWorker).
        /// Je zajištěno, že tato metoda není volána multithreadově (z různých vláken najednou).
        /// Nicméně je volána na jiném threadu, než na kterém byl objekt datového zdroje vytvořen.
		/// </summary>
		/// <param name="request">Požadovaná operace</param>
		void RunRequest(IDataSourceRequest request);
        /// <summary>
        /// Event, který datový zdroj vyvolá tehdy, když se změní data (například vlivem nastavení) a datový zdroj sám aktivně žádá o nějakou akci do grafické vrstvy.
        /// Typicky: přenačtení dat, změny rozsahu, a jiné změny.
        /// </summary>
        event DataSourceEventHandler DataChanged;
	}
	#endregion
	#region CLASS DataSourceProperties : vlastnosti datového zdroje
	/// <summary>
	/// Třída, která popisuje vlastnosti datového zdroje.
	/// Podle těchto vlastností se s tímto zdrojem zachází.
	/// </summary>
    public class DataSourceProperties
	{
		/// <summary>
		/// Název datového zdroje
		/// </summary>
		public string SourceName { get; set; }
	}
	#endregion
    #region CLASS GraphDeclarationCls : Deklarace vlastností grafu. GraphColumnDeclarationCls : deklarace vlastostí jednoho sloupce grafu. GraphRowDeclarationCls : deklarace vlastostí jednoho řádku grafu.
    /// <summary>
	/// Třída GraphDeclarationItemCls : Jedna položka deklarace grafu, obsahuje základní deklaraci z deklarátorů plus režijní data
	/// </summary>
    public class GraphDeclarationCls
	{
		#region KONSTRUKCE
		internal GraphDeclarationCls()
		{
		}
		public override string ToString()
		{
			return this.GraphCaption;
		}
		#endregion
		#region PROPERTY
		// Property z vestavěné deklarace:
		/// <summary>
		/// Výchozí režim grafu
		/// </summary>
		public RowGraphMode DefaultGraphMode { get; set; }
		/// <summary>
		/// Výchozí číslo třídy. Pokud bude kladné, předá se do datového zdroje pro načtení všech řádků této třídy.
		/// </summary>
		public int RowClassNumber { get; set; }
		/// <summary> { get; }
		/// Výchozí GID grafu. Skládá se z čísla třídy this.RowClassNumber a jako RecordNumber má 0.
		/// Nelze setovat, hodnotu lze vkládat do RowClassNumber.
		/// </summary>
		public GID GraphRowGId { get { return new GID(this.RowClassNumber, 0); } }
		/// <summary>
		/// Seznam čísel záznamů (číslo třídy a číslo záznamu) pro výchozí položky do zobrazení grafu
		/// </summary>
		public List<GID> RowList { get; set; }
		/// <summary>
		/// Objekt datového zdroje. Pokud má více grafů sdílet jeden datový zdroj, 
		/// musí se definice grafů zadat najednou a s jedním objektem datového zdroje.
		/// </summary>
		public IDataSource DataSource { get; set; }
		/// <summary>
		/// Libovolná informace předávaná spolu s grafem do požadavků do datového zdroje v requestu (v request.Tag)
		/// </summary>
		public object Tag { get; set; }
		/// <summary>
		/// Popisek grafu. 
		/// U grafu na celou stránku, anebo v horní polovině stránky jde o text na záložce, 
		/// u grafu v dolní polovině je text uveden na dělítku (Splitter).
		/// </summary>
		public string GraphCaption { get; set; }
        /// <summary>
        /// Doporučený layout grafu.
        /// Pokud zde bude uveden, nebude se načítat / ukládat implicitní.
        /// </summary>
        public IGraphLayout GraphLayout { get; set; }
		/// <summary>
		/// Barva záložky / dělítka
		/// </summary>
		public Color TabColor { get; set; }
		/// <summary>
		/// Barva pozadí řádku
		/// </summary>
		public Color RowColor { get; set; }
		/// <summary>
		/// Nejmenší výška řádku, pokud by se nenašel žádný element...
		/// </summary>
		public int RowHeightTotalMinPx { get; set; }
		/// <summary>
		/// Nejvyšší výška řádku grafu, v pixelech.
		/// </summary>
		public int RowHeightTotalMaxPx { get; set; }
		/// <summary>
		/// Typická výška jednoho řádku.
		/// </summary>
		public int RowHeightLineSolidPx { get; set; }
		/// <summary>
		/// Typická výška jednoho řádku, pokud jde o řádek typu RowGraphMode.MultiTask.
		/// </summary>
		public int RowHeightLineFragmentPx { get; set; }
		/// <summary>
		/// Výška nejmenšího zlomku v grafu typu RowGraphMode.MultiTask, kdy jsou zobrazeny položky využívající podíl kapacity.
		/// </summary>
		public int RowHeightMinFragmentPx { get; set; }
		/// <summary> { get; }
		/// Přídavek k výšce neděleného řádku, vyjádřený relativně k hodnotě this.RowHeightOneLine (fyzická výška jedné linky).
		/// </summary>
		public decimal RowHeightAddLineSolidRatio { get; set; }
		/// <summary> { get; }
		/// Přídavek k výšce děleného řádku, vyjádřený relativně k hodnotě this.RowHeightOneLine (fyzická výška jedné linky).
		/// </summary>
		public decimal RowHeightAddLineFragmentRatio { get; set; }
		/// <summary>
		/// Vrstva, kam se vykreslí linky časové osy v tomto grafu.
		/// Default = SubElements.
		/// </summary>
		public GraphLayerType TimeTickLayer { get; set; }
		/// <summary>
		/// Vrstva, kam se vykreslí linky jednotek v grafu kapacitních jednotek, kde jsou kresleny fragmenty (částečné = podílové využití kapacity).
		/// Default = SubElements.
		/// </summary>
		public GraphLayerType FragmentLineLayer { get; set; }
		/// <summary>
		/// Soupis sloupců a jejich vlastností
		/// </summary>
		public List<GraphColumnDeclarationCls> Columns { get; set; }
		#endregion
	}
	/// <summary>
	/// Deklarace vlastností jednoho sloupce grafu
	/// </summary>
    public class GraphColumnDeclarationCls
	{
		public GraphColumnDeclarationCls()
		{
			this._Reset();
		}
		public override string ToString()
		{
			return this.Text + " (" + this.HeaderMode.ToString() + "; Width=" + this.Width.ToString() + ")";
		}
		private void _Reset()
		{
			this.Key = null;
			this.Text = null;
			this.RowFilterVisible = false;
			this.HeaderMode = DColumnHeaderMode.StandardHeader;
			this.RowFilterItemName = null;
			this.Visible = true;
			this.Enabled = true;
			this.ResizeWidthToFillParent = false;
			this.Width = 100;
			this.MinimumWidth = null;
			this.MaximumWidth = null;
			this.IsResizable = true;
			this.IsMovable = false;
			this.IsSortEnabled = true;
			this.SortMode = ColumnSortMode.None;
			this.Alignment = ContentAlignment.MiddleCenter;
            this.ContentAlignment = ContentAlignment.MiddleLeft;
			this.Tag = null;
		}
		/// <summary>
		/// Klíč sloupce. Pokud je zadaný, lze podle něj sloupec identifikovat (najít). Nesmí být duplicitní.
		/// </summary>
		public string Key { get; set; }
		/// <summary>
		/// Text v ColumnHeader. Může obsahovat NewLine.
		/// </summary>
		public string Text { get; set; }
		/// <summary>
		/// Příznak, že pro daný column má být zobrazen řádkový filtr
		/// </summary>
		public bool RowFilterVisible { get; set; }
		/// <summary>
		/// Režim zobrazení záhlaví sloupce. Výchozí hodnota je DColumnHeaderMode.StandardHeader.
		/// Lze nastavit režim Časová osa, tento režim smí být použit nanejvýše u jednoho sloupce.
		/// Objekt časové osy je dostupný v property DColumns.TimeAxis.
		/// Pod časovou osou může/nemusí být zobrazen řádkový filtr, záleží na property DColumn.RowFilterVisible
		/// </summary>
		public DColumnHeaderMode HeaderMode { get; set; }
		/// <summary>
		/// Klíčový název položky v tomto sloupci. Tento název se bude objevovat v this.RowFilterItem v property ItemName. Typicky obsahuje název hodnoty, která je v tomto sloupci zobrazována.
		/// Pokud není zadaná hodnota, vrací this.Key.
		/// </summary>
		public string RowFilterItemName { get; set; }
		/// <summary>
		/// Viditelnost sloupce
		/// </summary>
		public bool Visible { get; set; }
		/// <summary>
		/// Dostupnost sloupce (Enabled / Disabled)
		/// </summary>
		public bool Enabled { get; set; }
		/// <summary>
		/// Tento sloupec se má automaticky přizpůsobovat šířce Parenta (tj. řada záhlaví sloupců) tak, aby Parent byl celý naplněn sloupci.
		/// Hodnotu true lze zadat pouze do jednoho sloupce. Zadání true do jednoho sloupce způsobí, že v ostatních sloupcích bude hodnota false.
		/// Sloupec stále akceptuje hodnoty MinimumWidth a MaximumWidth.
		/// </summary>
		public bool ResizeWidthToFillParent { get; set; }
		/// <summary>
		/// Šířka tohoto sloupce.
		/// Změna hodnoty se projeví voláním eventu Changed, a ne Changing.
		/// Lze ji omezit hodnotami MinimumWidth a MaximumWidth.
		/// </summary>
		public int Width { get; set; }
		/// <summary>
		/// Nejmenší povolená šířka
		/// </summary>
		public int? MinimumWidth { get; set; }
		/// <summary>
		/// Největší povolená šířka
		/// </summary>
		public int? MaximumWidth { get; set; }
		/// <summary>
		/// Lze tomuto sloupci měnit šířku?
		/// </summary>
		public bool IsResizable { get; set; }
		/// <summary>
		/// Lze tento sloupec přemístit na jiné pořadí?
		/// </summary>
		public bool IsMovable { get; set; }
		/// <summary>
		/// Lze tímto sloupcem třídit? Pak může reagovat na Click a nastavovat this.SortOrder.
		/// </summary>
		public bool IsSortEnabled { get; set; }
		/// <summary>
		/// Aktuální stav třídění podle tohoto sloupce.
		/// Po změně je vyvolán event RowFilterChanged. Třídění je uvedeno v objektu RowFilter.
		/// </summary>
		public ColumnSortMode SortMode { get; set; }
		/// <summary>
        /// Zarovnání textu v hlavičce.
        /// Default = ContentAlignment.MiddleCenter
		/// </summary>
		public ContentAlignment Alignment { get; set; }
        /// <summary>
        /// Zarovnání obsahu sloupce.
        /// Default = ContentAlignment.MiddleLeft
        /// </summary>
        public ContentAlignment ContentAlignment { get; set; }
		/// <summary>
		/// Tag, který ukládá libovolná data.
		/// </summary>
		public object Tag { get; set; }
	}
    /// <summary>
    /// GraphRowDeclarationCls : deklarace vlastostí jednoho řádku grafu.
    /// </summary>
    public class GraphRowDeclarationCls
    {
        #region Konstruktor, property
        public GraphRowDeclarationCls()
        {
            this.RowGraph = RowGraphMode.MultiTask;
            this.Properties = RowProperties.DynamicElementsLoading | RowProperties.DynamicSubNodeLoading | RowProperties.ChildSortedText;
            this.RowHeightMultiplier = 1F;
            this.ActionOnRowDoubleClick = RowActionType.ZoomTimeToAllElementsOnRow;
            this.ActionOnElementDoubleClick = RowActionType.ZoomTimeToCurrentElements;
            this.ShowPrevNextIcon = false;
            this.ReloadSubNodesOnExpandNode = false;
        }
        /// <summary>
        /// Druh grafu v tomto řádku.
        /// Default = RowGraphMode.MultiTask
        /// </summary>
        public RowGraphMode RowGraph { get; set; }
        /// <summary>
        /// Sada příznaků, které definují chování nodu z hlediska vytváření řádku.
        /// Default = RowProperties.DynamicElementsLoading | RowProperties.DynamicSubNodeLoading | RowProperties.ChildSortedText;
        /// Pro detekci jednotlivých stavů lze využít property typu .IsXxxx
        /// </summary>
        public RowProperties Properties { get; set; }
        /// <summary>
        /// Násobek výšky řádku.
        /// Default = 1F
        /// </summary>
        public float RowHeightMultiplier { get; set; }
        /// <summary>
        /// Akce po doubleclicku na řádek mimo element.
        /// Default = 
        /// </summary>
        public RowActionType ActionOnRowDoubleClick { get; set; }
        /// <summary>
        /// Akce po doubleclicku na element.
        /// Default = 
        /// </summary>
        public RowActionType ActionOnElementDoubleClick { get; set; }
        /// <summary>
        /// Zobrazovat ikony Vlevo - Vpravo na řádku pod myší.
        /// Default = false
        /// </summary>
        public bool ShowPrevNextIcon { get; set; }
        /// <summary>
        /// Vyžádat si reload řádků vždy op jejich rozbalení.
        /// Default = false;
        /// </summary>
        public bool ReloadSubNodesOnExpandNode { get; set; }
        /// <summary>
        /// Ikona řádku, zobrazuje se v prvním sloupci před textem, za ikonami TreeLines.
        /// Default = null
        /// </summary>
        public System.Drawing.Image Icon { get; set; }
        /// <summary>
        /// Barva pozadí tohoto řádku..
        /// Default = Empty = přebírá se barva grafu.
        /// </summary>
        public System.Drawing.Color RowColor { get; set; }
        /// <summary>
        /// Nejmenší výška řádku grafu, v pixelech.
        /// Pokud nebude zadáno, převezme se z deklarace grafu.
        /// </summary>
        public int? RowHeightTotalMinPx { get; set; }
        /// <summary>
        /// Nejvyšší výška řádku grafu, v pixelech.
        /// Pokud nebude zadáno, převezme se z deklarace grafu.
        /// </summary>
        public int? RowHeightTotalMaxPx { get; set; }
        /// <summary>
        /// Typická výška jedné linky řádku (linka v MultiThread grafu odpovídá výšce jednoho elementu s UseRatio = 1.0M), u ostatních grafů jde o běžnou výšku elementu.
        /// Pokud nebude zadáno, převezme se z deklarace grafu.
        /// </summary>
        public int? RowHeightLineSolidPx { get; set; }
        /// <summary>
        /// <para>
        /// Typická výška jednoho řádku, pokud jde o řádek typu RowGraphMode.MultiTask, kde elementy mají UseRatio různé od 1.0M
        /// </para>
        /// <para>
        /// Pro graf typu BarGraph je zde určena výška jednotky, v níž jsou uváděny výšky elementů (jde o údaj v IDataElement.ElementHeightRatio)
        /// Pokud nebude zadáno, převezme se z deklarace grafu.
        /// </para>
        /// </summary>
        public int? RowHeightLineFragmentPx { get; set; }
        /// <summary>
        /// Výška nejmenšího zlomku v grafu typu RowGraphMode.MultiTask, kdy jsou zobrazeny položky využívající podíl kapacity.
        /// Pokud nebude zadáno, převezme se z deklarace grafu.
        /// </summary>
        public int? RowHeightMinFragmentPx { get; set; }
        /// <summary> { get; }
        /// Přídavek k výšce neděleného řádku, vyjádřený relativně k hodnotě this.RowHeightLineSolidPx (fyzická výška jedné nedělené linky).
        /// Pokud nebude zadáno, převezme se z deklarace grafu.
        /// </summary>
        public decimal? RowHeightAddLineSolidRatio { get; set; }
        /// <summary> { get; }
        /// Přídavek k výšce děleného řádku, vyjádřený relativně k hodnotě this.RowHeightLineFragmentPx (fyzická výška jedné dělené linky).
        /// Pokud nebude zadáno, převezme se z deklarace grafu.
        /// </summary>
        public decimal? RowHeightAddLineFragmentRatio { get; set; }
		#endregion
        #region Jednoduché detektory základních hodnot Properties (this.Properties => this.IsDynamicElementsLoading, atd)
        /// <summary>
        /// Subnody třídit podle klíče. Pokud se třídit nebude, budou subnody vráceny v pořadí zadávání.
        /// </summary>
        public bool IsChildSortedKey { get { return ((this.Properties & RowProperties.ChildSortedKey) > 0); } }
        /// <summary>
        /// Subnody třídit podle textu. Pokud se třídit nebude, budou subnody vráceny v pořadí zadávání.
        /// </summary>
        public bool IsChildSortedText { get { return ((this.Properties & RowProperties.ChildSortedText) > 0); } }
        /// <summary>
        /// Node má subnody dynamicky načítané: prezentuje se, jako by subnody měl, i v situaci kdy Childs je prázdné
        /// </summary>
        public bool IsDynamicSubNodeLoading { get { return ((this.Properties & RowProperties.DynamicSubNodeLoading) > 0); } }
        /// <summary>
        /// Node má dynamicky načítané elementy. Pokud není zvoleno, pak do vytvářeného řádku vloží své elementy a nastaví AllElementsLoaded.
        /// Pokud ano, pak se do nově vygenerovaného řádku nevkládají všechny elementy, ale graf sám si o ně požádá.
        /// Pokud ne, pak se do nově vygenerovaného řádku vloží všechny elementy a nastaví se AllElementsLoaded = true, pak si graf o další elementy nikdy neřekne.
        /// </summary>
        public bool IsDynamicElementsLoading { get { return ((this.Properties & RowProperties.DynamicElementsLoading) > 0); } }
        /// <summary>
        /// Node má elementy načítané dynamicky, ale v okamžiku vytváření řádku je vhodné do něj uložit ty elementy, které odpovídají výchozímu času.
        /// Tím se nezruší dynamické donačítání elementů, ale po první dotaz se nevrátí prázdný řádek který si vyžádá další request na elementy.
        /// Do vygenerovaného řádku je třeba vepsat TimeRange, aby graf věděl, že za toto období má elementy načtené a že je již nemusí načítat.
        /// </summary>
        public bool IsPreLoadingElements { get { return ((this.Properties & RowProperties.PreLoadingElements) > 0); } }
        #endregion
        #region Statické konstruktory defaultních deklarací
        /// <summary>
        /// Vrátí deklaraci řádku s grafem MultiTask s danými rozměry a properties (parametry).
        /// Další property jsou nastaveny fixně: RowGraph = MultiTask, ActionOnRowDoubleClick = ZoomTimeToAllElementsOnRow, ActionOnElementDoubleClick = ZoomTimeToCurrentElements,
        /// ostatní jsou výchozí.
        /// </summary>
        /// <param name="rowHeightLineSolidPx"></param>
        /// <param name="rowHeightAddLineSolidRatio"></param>
        /// <param name="properties"></param>
        /// <returns></returns>
        public static GraphRowDeclarationCls StandardMultiTask(int rowHeightLineSolidPx, decimal rowHeightAddLineSolidRatio, RowProperties properties)
        {
            GraphRowDeclarationCls d = new GraphRowDeclarationCls();
            d.RowGraph = RowGraphMode.MultiTask;
            d.Properties = properties;
            d.ActionOnRowDoubleClick = RowActionType.ZoomTimeToAllElementsOnRow;
            d.ActionOnElementDoubleClick = RowActionType.ZoomTimeToCurrentElements;
            d.RowHeightLineSolidPx = rowHeightLineSolidPx;
            d.RowHeightAddLineSolidRatio = rowHeightAddLineSolidRatio;
            return d;
        }
        /// <summary>
        /// Vrátí deklaraci řádku s grafem MultiTask s danými rozměry a properties (parametry).
        /// Další property jsou nastaveny fixně: RowGraph = MultiTask, ActionOnRowDoubleClick = ZoomTimeToAllElementsOnRow, ActionOnElementDoubleClick = ZoomTimeToCurrentElements,
        /// ostatní jsou výchozí.
        /// </summary>
        /// <param name="rowHeightLineSolidPx"></param>
        /// <param name="rowHeightAddLineSolidRatio"></param>
        /// <param name="properties"></param>
        /// <returns></returns>
        public static GraphRowDeclarationCls StandardLine(int rowHeightLineSolidPx, decimal rowHeightAddLineSolidRatio, RowProperties properties)
        {
            GraphRowDeclarationCls d = new GraphRowDeclarationCls();
            d.RowGraph = RowGraphMode.Line;
            d.Properties = properties;
            d.ActionOnRowDoubleClick = RowActionType.ZoomTimeToAllElementsOnRow;
            d.ActionOnElementDoubleClick = RowActionType.ZoomTimeToCurrentElements;
            d.RowHeightLineSolidPx = rowHeightLineSolidPx;
            d.RowHeightAddLineSolidRatio = rowHeightAddLineSolidRatio;
            return d;
        }
		/// <summary>
		/// Vrátí deklaraci řádku s grafem BarGraph s danými rozměry a properties (parametry).
		/// Další property jsou nastaveny fixně: RowGraph = MultiTask, ActionOnRowDoubleClick = ZoomTimeToAllElementsOnRow, ActionOnElementDoubleClick = ZoomTimeToCurrentElements,
		/// ostatní jsou výchozí.
		/// </summary>
		/// <param name="rowHeightLineSolidPx"></param>
		/// <param name="rowHeightAddLineSolidRatio"></param>
		/// <param name="properties"></param>
		/// <returns></returns>
		public static GraphRowDeclarationCls StandardBarGraph(int rowHeightLineSolidPx, decimal rowHeightAddLineSolidRatio, RowProperties properties)
		{
			GraphRowDeclarationCls d = new GraphRowDeclarationCls();
			d.RowGraph = RowGraphMode.BarGraph;
			d.Properties = properties;
			d.ActionOnRowDoubleClick = RowActionType.ZoomTimeToAllElementsOnRow;
			d.ActionOnElementDoubleClick = RowActionType.ZoomTimeToCurrentElements;
			d.RowHeightLineSolidPx = rowHeightLineSolidPx;
			d.RowHeightAddLineSolidRatio = rowHeightAddLineSolidRatio;
			return d;
		}
		#endregion
    }
	#endregion
    #region INTERFACE IDataSourceRequest, ENUM DataSourceRequestType, DELEGÁT a EVENTARGS PRO DataSourceEvent
    /// <summary>
    /// Minimalistické požadavky na request do datového zdroje.
    /// Ostatní data deklaruje konkrétní potomstvo.
    /// </summary>
    public interface IDataSourceRequest
    {
        /// <summary>
        /// Typ požadavku
        /// </summary>
        DataSourceRequestType RequestType { get; }
        /// <summary>
        /// Pokud běh požadavku skončil s chybou, pak je uložena zde.
        /// </summary>
        Exception ResultException { get; }
    }
    public delegate void DataSourceEventHandler(object sender, DataSourceEventArgs args);
	/// <summary>
	/// Data, která předává datový zdroj do vizuální vrstvy poté, kdy v něm došlo ke změně dat z důvodu jiné aktivity, než je požadavek grafické vrstvy.
	/// </summary>
    public class DataSourceEventArgs : EventArgs
    {
		public DataSourceEventArgs()
		{
		}
        public static DataSourceEventArgs CreateInvalidateTimeRange(TimeRange invalidateTimeRange)
        {
            DataSourceEventArgs args = new DataSourceEventArgs();
            args.InvalidateTimeRange = invalidateTimeRange;
            return args;
        }
        public static DataSourceEventArgs CreateInvalidateElementInAllRows(bool collapseAllNodes)
        {
            DataSourceEventArgs args = new DataSourceEventArgs();
            args.InvalidateElementsInAllRows = true;
            args.CollapseAllNodes = collapseAllNodes;
            return args;
        }
        /// <summary>
        /// Požadavek na ReDraw jednoho řádku (plus přenačtení elementů).
        /// </summary>
        /// <param name="rowGId">GID vizuálního řádku</param>
        /// <param name="reloadElements">Požadavek, aby si vizuální vrstva znovu načetla všechny elementy. 
        /// Bez tohoto požadavku (false) dojde jen k překreslení elementů.
        /// Díky tomu, že elementy mají kořeny v datové vrstvě (stále v sobě nesou referenci na IDataElement), promítnou se změny v datech do vizuálních elementů.
        /// Pokud bude zadáno true, dojde i k načtení nových prvků anebo k odstranění smazaných prvků. Seznam prvků je v objektu NodeInfo, který je základnou vizuálního řádku.
        /// </param>
        /// <returns></returns>
        internal static DataSourceEventArgs CreateReDrawRow(GID rowGId, bool reloadElements)
        {
            DataSourceEventArgs args = new DataSourceEventArgs();
            args.ReDrawRowGId = rowGId;
            args.ReDrawRowReloadElements = reloadElements;
            return args;
        }
        /// <summary>
		/// Datový zdroj zjistil nová data / změnu dat pro uvedený časový úsek.
		/// Grafická vrstva by měla invalidovat tento čas a načíst jej znovu, pro všechny řádky.
		/// </summary>
		public TimeRange InvalidateTimeRange { get; private set; }
        /// <summary>
        /// Datový zdroj zjistil nová data / změnu dat pro uvedený časový úsek.
        /// Grafická vrstva by měla invalidovat tento čas a načíst jej znovu, pro všechny řádky.
        /// </summary>
        public bool InvalidateElementsInAllRows { get; private set; }
        /// <summary>
        /// Požadavek na Close všech nodů.
        /// </summary>
        public bool CollapseAllNodes { get; private set; }
        /// <summary>
        /// Požadavek na překreslení daného řádku
        /// </summary>
        public GID ReDrawRowGId { get; private set; }
        /// <summary>
        /// Požadavek na reload elementů řádku ReDrawRowGId před jeho překreslením
        /// </summary>
        public bool ReDrawRowReloadElements { get; private set; }
    }
    #endregion
    #region ENUM DataSourceRequestType : TYPY POŽADAVKŮ NA DATOVÝ ZDROJ. DALŠÍ POŽADAVKY PŘIDÁVAT SEM.
    /// <summary>
    /// Typy požadavků na datový zdroj. Ty se budou průběžně přidávat...
    /// </summary>
    public enum DataSourceRequestType
    {
        None = 1,
		Initialize,
        ReadRows,
        ReadElementsForRows,
        ReadSpecific,
		RunFunction
    }
    #endregion
    #region INTERFACE IDataRow : jeden řádek grafu
    /// <summary>
	/// Interface, definující jeden řádek grafu
	/// </summary>
	public interface IDataRow
	{
		/// <summary>
		/// Globální identifikátor tohoto záznamu.
		/// </summary>
		GID GId { get; }
        /// <summary>
        /// Jméno nodu. Mělo by být unikátní, zatím ale unikátnost není kontrolována. Používá se při persistenci pointerů na řádek(řádky).
        /// GID se může při příštím reloadu dat změnit, ale NodeName by nemělo.
        /// </summary>
        string NodeName { get; }
		/// <summary>
		/// Příznak, zda tento řádek má své pod-uzly (subnodes), tj. můžeme pro něj zobrazit ikonku [+] ve stromu
		/// </summary>
		bool HasSubNodes { get; set; }
		/// <summary>
		/// Druh grafu, který je pro tento řádek zobrazen
		/// </summary>
		RowGraphMode RowGraph { get; set; }
		/// <summary>
		/// Násobek obvyklé výšky řádku pro tuto položku.
		/// Default = 1 pro běžné textové řádky.
		/// </summary>
		float RowHeightMultiplier { get; set; }
		/// <summary>
		/// Globální identifikátor záznamu parenta.
		/// Typicky se parent nevepisuje: systém typicky funguje tak, že parent je ten objekt, pro který jsou načítány jeho podřízené prvky.
		/// RowGId lze setovat. Vizuální vrstva jej přebírá po vrácení dat, ale pro svoji další interní práci si uchovává RowGId jinde.
		/// Vztah na Parenta je tedy řešen na úrovni grafiky, která požádala o načtení podřízených záznamů.
		/// Nicméně je možno při načítání podřízených záznamů rovnou načíst i hlubší podřízené záznamy, a jim pak vyplnit RowGId na explicitní záznam.
		/// Například: máme načíst všechny operace pro jeden výrobní příkaz.
		/// Načteme 6 operací, a do nich nevyplňujeme RowGId (což je defaultní chování).
		/// Nad rámec operací se rozhodneme načíst i komponenty operací, tedy podřízené řádky.
		/// Pak pro každou ze 6 operací najdeme její komponenty, načteme je, do každé komponenty vložíme RowGId = GId její operace, 
		/// a komponenty přidáme do výsledného seznamu dat. Sestavení struktury stromu pak zajistí vizuální vrstva.
		/// Toto je navíc i rekurzivní možnost.
		/// </summary>
		GID ParentGId { get; set; }
        /// <summary>
        /// GID příštího řádku. Typicky je Empty, takový řádek se přidává na konec seznamu nodů do parent nodu.
        /// Pokud ale je NextGId notEmpty, pak se systém pokusí jej zařadit do seznamu subnodes tak, aby byl před prvkem NextGId. (Pokud takový prvek nenajde, zařadí tento řádek na konec).
        /// </summary>
        GID NextGId { get; set; }
		/// <summary>
		/// Pole elementů (časové položky grafu), které jsou načítány společně s řádkem.
		/// Ve výchozím stavu je null !
		/// Některé datové typy jsou konstruovány tak, že časová položka je nedílnou součástí řádku 
		/// (např. operace výrobního příkazu je současně řádkem grafu, a současně časovou položkou). 
		/// Pak je vhodné vygenerovat časové položky společně s položkou řádku, a uložit informace do tohoto pole.
		/// Metoda GetRows tak vyřeší načítání jak řádku, tak časových elementů.
		/// Pokud jsou touto metodou načteny všechny časové úseky (např. může existovat jen jeden čas, a ten je uložen do tohoto pole),
		/// pak je třeba nastavit this.AllElementsLoaded = true, a řídící jednotka grafu pak nebude nikdy donačítat data pro širší časové úseky.
		/// Tento mechanismus se nehodí pro objekty, které mají časově široké rozmístění mnoha elementů, typicky stavy kapacit.
        /// Pokud jsou načteny elementy jen pro omezený časový interval, pak je vhodné tento interval uložit do this.ElementLoadedTimeRange.
        /// Grafická vrstva si pak zapamatuje, že pro toto období už má elementy načtené a nebude je vyžadovat znovu.
		/// </summary>
		List<IDataElement> ElementList { get; set; }
        /// <summary>
        /// Časový interval, pro který jsou načteny elementy v this.ElementList.
        /// Elementy mohou fyzicky pokrývat menší úsek, než je uvedeno v this.ElementLoadedTimeRange - protože ne v každém čase musí být nějaký element.
        /// </summary>
        TimeRange ElementLoadedTimeRange { get; set; }
		/// <summary>
		/// Příznak, že elementy načtené do pole this.ElementList představují úplnou sadu elementů, 
		/// a pro tento řádek (this) nebude nikdy zapotřebí donačítat elementy pro širší časové pole.
		/// </summary>
		bool AllElementsLoaded { get; set; }
        /// <summary>
        /// Akce po doubleclicku na řádek (ne na element, tedy někde do volného místa nebo do záhlaví)
        /// </summary>
        RowActionType ActionOnRowDoubleClick { get; }
        /// <summary>
        /// Akce po doubleclicku na element
        /// </summary>
        RowActionType ActionOnElementDoubleClick { get; }
		/// <summary>
		/// Zobrazovat na řádku s myší ikony Vlevo / Vpravo ?
		/// </summary>
		bool ShowPrevNextIcon { get; }
        /// <summary>
        /// Příznak, že je požadováno přenačtení subnodů po každém otevření tohoto nodu
        /// </summary>
        bool ReloadSubNodesOnExpandNode { get; set; }
        /// <summary>
		/// Ikona pro tento řádek
		/// </summary>
		Image Icon { get; }
		/// <summary>
		/// Umístění ikony (icon) v tomto řádku
		/// </summary>
		ContentAlignment IconAlignment { get; }
        /// <summary>
        /// Barva pozadí. Pokud je Empty, neuplatní se.
        /// </summary>
        Color RowColor { get; }
		/// <summary>
		/// Nejmenší výška řádku grafu, v pixelech.
		/// Pokud nebude zadáno, převezme se z deklarace grafu.
		/// </summary>
		int? RowHeightTotalMinPx { get; }
		/// <summary>
		/// Nejvyšší výška řádku grafu, v pixelech.
		/// Pokud nebude zadáno, převezme se z deklarace grafu.
		/// </summary>
		int? RowHeightTotalMaxPx { get; }
		/// <summary>
		/// Typická výška jedné linky řádku (linka v MultiThread grafu odpovídá výšce jednoho elementu s UseRatio = 1.0M), u ostatních grafů jde o běžnou výšku elementu.
		/// Pokud nebude zadáno, převezme se z deklarace grafu.
		/// </summary>
		int? RowHeightLineSolidPx { get; }
		/// <summary>
		/// Typická výška jednoho řádku, pokud jde o řádek typu RowGraphMode.MultiTask, kde elementy mají UseRatio různé od 1.0M
		/// Pokud nebude zadáno, převezme se z deklarace grafu.
		/// </summary>
		int? RowHeightLineFragmentPx { get; }
		/// <summary>
		/// Výška nejmenšího zlomku v grafu typu RowGraphMode.MultiTask, kdy jsou zobrazeny položky využívající podíl kapacity.
		/// Pokud nebude zadáno, převezme se z deklarace grafu.
		/// </summary>
		int? RowHeightMinFragmentPx { get; }
		/// <summary> { get; }
		/// Přídavek k výšce neděleného řádku, vyjádřený relativně k hodnotě this.RowHeightLineSolidPx (fyzická výška jedné nedělené linky).
		/// Pokud nebude zadáno, převezme se z deklarace grafu.
		/// </summary>
		decimal? RowHeightAddLineSolidRatio { get; }
		/// <summary> { get; }
		/// Přídavek k výšce děleného řádku, vyjádřený relativně k hodnotě this.RowHeightLineFragmentPx (fyzická výška jedné dělené linky).
		/// Pokud nebude zadáno, převezme se z deklarace grafu.
		/// </summary>
		decimal? RowHeightAddLineFragmentRatio { get; }
		/// <summary>
		/// Vrátí text do sloupce daného indexu.
		/// Index sloupce je odvozen od pořadí sloupce.
		/// </summary>
		/// <param name="index">Index sloupce</param>
		/// <param name="key">Klíč sloupce</param>
		string GetColumnContent(int index, string key);
        /// <summary>
        /// Vrátí hodnotu daného sloupce, která se použije jako hodnota vstupující do řádkového filtru.
        /// Pokud se vrátí null, pak si systém načte hodnotu pomocí metody GetColumnContent().
        /// Je tak zajištěna možnost uživatelského formátování zobrazeného textu, a současně možnost filtrování podle neupravené hodnoty textu.
        /// Typicky je možno zobrazovat čas jako "12 651 ms" (vrátí metoda GetColumnContent()), ale filtrovat na hodnotu "50", což je menší!
        /// (při textovém porovnání by bylo "50" větší než "12 651 ms" !!!)
        /// Pokud není třeba toto chování podpořit, lze vždy vrátit hodnotu null.
        /// </summary>
        /// <param name="index">Index sloupce</param>
        /// <param name="key">Klíč sloupce</param>
        string GetColumnValue(int index, string key);
		/// <summary>
		/// Vrátí text, který se zobrazuje v ToolTipu.
		/// Může vrátit null, pak se za tento objekt nic nezobrazí.
		/// Může vrátit text, obsahující CrLf, pak bude text odřádkován.
		/// </summary>
		string ToolTipInfo();
	}
	#endregion
	#region INTERFACE IDataElement : jeden grafický element grafu
	/// <summary>
	/// Interface, definující jeden grafický element grafu
	/// </summary>
	public interface IDataElement
	{
        /// <summary>
        /// Element je viditelný (někdy může být zhasnutý, když mu třeba není dobře a nechce být viděn)
        /// </summary>
        bool ElementVisible { get; }
		/// <summary>
		/// Globální identifikátor záznamu = tohoto elementu
		/// </summary>
		GID GId { get; }
		/// <summary>
		/// Časový interval tohoto elementu (od kdy do kdy trvá).
		/// Jde o aktuální údaj, který může obsahovat editovanou hodnotu.
		/// </summary>
		TimeRange TimeRange { get; set; }
		/// <summary>
		/// Výška elementu v poměru k výšce jedné linky řádku, uplatňuje se pouze u grafu typu BarGraph.
        /// Tento graf vykresluje elementy ve výšce dané touto hodnotou, 
        /// kde hodnotě ElementHeightRatio == 1.0f odpovídá počet pixelů 
        /// definovaný v deklaraci grafu nebo řádku: GraphRowDeclarationCls.RowHeightLineFragmentPx.
        /// Výška celého řádku je daná dynamicky tak, aby zobrazila i nejvyšší element.
        /// Autor grafu by měl předem pouze odhadnout očekávané rozmezí hodnot this.ElementHeightRatio, 
        /// a tomu uzpůsobit deklarovanou výšku jednotky v GraphRowDeclarationCls.RowHeightLineFragmentPx.
		/// </summary>
		float ElementHeightRatio { get; }
        /// <summary>
        /// true: Začátek intervalu je nejistý (čas počátku odhadujeme podle počátku nadřízeného objektu, ale jistitu nemáme)
        /// </summary>
        bool BeginIsUncertain { get; }
        /// <summary>
        /// true: Konec intervalu je nejistý (čas počátku odhadujeme podle počátku nadřízeného objektu, ale jistitu nemáme)
        /// </summary>
        bool EndIsUncertain { get; }
        /// <summary>
		/// Pomocný údaj pro třídění, pro případy shodného času Begin
		/// </summary>
		int SubTimeSort { get; }
		/// <summary>
		/// Příznak, že tento element není "časový" ale "celořádkový".
		/// Praktické použití je jen u Temp elementu při načítání podřízených řádků, kdy element nereprezentuje čas, ale obsazení celého řádku.
		/// </summary>
		bool FullRow { get; }
        /// <summary>
        /// Příznak, že pokud má element čas s nulovou délkou (kterou by systém dokázal vykreslit), je žádoucí kreslení rectangle potlačit, bude se vykreslovat pouze Image.
        /// </summary>
        bool HideZeroWidthElementRectangle { get; }
		/// <summary>
		/// Zlomky elementu, převezme si je vhodný painter
		/// </summary>
		float[] Fragments { get; }
		/// <summary>
		/// Příslušnost data do vrstvy.
		/// Odlišuje vrstvu podkladovou (typicky zobrazení směny) a vrstvu datovou (aktivita v čase, která může být delší / kratší než směna).
		/// </summary>
		GraphLayerType ElementLayer { get; }
		/// <summary>
		/// Příslušnost elementu do skupiny.
		/// V grafu typu MultiThread jsou elementy skládány "nad sebe", a jsou členěny do skupin (Groups).
		/// Elementy jedné skupiny jsou ve své "řádce", a nemíchají se do řádky jiných skupin.
		/// Implicitní hodnota je 0.
		/// </summary>
		int ElementGroup { get; }
		/// <summary>
		/// Tvar elementu.
		/// </summary>
		GraphElementShapeType ElementShapeType { get; }
        /// <summary>
        /// Vlastnosti elementu
        /// </summary>
        ElementProperties Properties { get; }
        /// <summary>
        /// Akce, kterou má tento element provést po doubleclicku.
        /// Výchozí hodnota je ElementActionType.DefaultByRow, provede se to co je deklarované pro řádek na němž tento element leží.
        /// Je možno specifikovat akci ElementActionType.ExecFunction, pak se vyhledá vhodný Plugin a ten se provede.
        /// </summary>
        ElementActionType ActionOnDoubleClick { get; }
        /// <summary>
        /// Handler eventu DoubleClick. Pokud se má vyvolat, je třeba v property ActionOnDoubleClick vracet hodnotu ExecHandler (jinak se handler nevyvolá!).
        /// </summary>
        GraphElementHandler DoubleClick { get; }
		/// <summary>
		/// Barevná skupina elementu, může být null
		/// </summary>
		string ColorGroup { get; }
		/// <summary>
		/// Barva pozadí elementu
		/// </summary>
        Color BackColor { get; set; }
		/// <summary>
		/// Barva písma v elementu
		/// </summary>
		Color FontColor { get; }
        /// <summary>
        /// Příznak, že Caption (text v elementu) má být zobrazen vždy když se vejde, nejen pod myší.
        /// </summary>
        bool CaptionShowAllways { get; }
		/// <summary>
		/// Obrázek, který se kreslí u elementu
		/// </summary>
		Image ElementImage { get; }
		/// <summary>
		/// Umístění obrázku vzhledem k elementu:
		/// Určení bodu na okraji elementu, k němuž se bude obrázek zarovnávat
		/// </summary>
		ContentAlignment ImagePivotElementPoint { get; }
		/// <summary>
		/// Umístění obrázku vzhledem k elementu:
		/// Určení bodu Image, který se bude zarovnávat k bodu ImagePivotElementPoint
		/// </summary>
		ContentAlignment ImagePivotImagePoint { get; }
        /// <summary>
        /// Obsahuje (vrací) text, který se zobrazuje v ToolTipu.
        /// Může vrátit null, pak se za tento objekt nic nezobrazí.
        /// Může vrátit text, obsahující CrLf, pak bude text odřádkován.
        /// </summary>
        string ToolTipInfo { get; }
        /// <summary>
        /// Obsahuje (vrací) sadu textů pro vepsání do elementu.
        /// Pokud zde bude null, zkusí GUI použít metodu IDataElement.GetCaption().
        /// Pokud zde bude pole, pak si GUI sama najde text, který se do elementu vejde vepsat.
        /// </summary>
        string[] Captions { get; }

        /// <summary>
        /// Tato metoda se volá jen tehdy, když v property IDataElement.ToolTipInfo je null.
        /// Vrátí text, který se zobrazuje v ToolTipu.
        /// Může vrátit null, pak se za tento objekt nic nezobrazí.
        /// Může vrátit text, obsahující CrLf, pak bude text odřádkován.
        /// </summary>
        string GetToolTipInfo(IDataRow rowData);
        /// <summary>
        /// Tato metoda se volá jen tehdy, když v property IDataElement.Captions je null.
        /// Vrátí text, který se zobrazuje v obdélníku elementu při jeho "zaměření", například při editaci.
        /// Jde o krátkou, zásadně jednořádkovou informaci, jejíž délka (počet znaků) je omezena 
        /// fyzickou velikostí elementu při aktuálním rozlišení.
        /// </summary>
        /// <param name="rowData">Data o řádku, v němž se element nachází. Řádek může obsahovat některé potřebné informace.</param>
        /// <param name="charCount">Nejvyšší počet aktuálně zobrazitelných znaků. 
        /// Pokud bude vrácený text obsahovat více znaků, budou pravděpodobně oříznuty. 
        /// Pravděpodobnost je způsobena proporcionálním písmem. 
        /// Daný počet znaků je vypočten na maximální šířku znaku, jde tedy o garantovaný zobrazitelný počet. 
        /// Pokud bude vrácen text delší, ale složený z užších znaků, možná se podaří je zobrazit korektně. 
        /// Jsme v grafickém prostředí Windows...</param>
        /// <returns></returns>
        string GetCaption(IDataRow rowData, float charCount);
		/// <summary>
        /// Umožní klientovi vykreslit tento element.
        /// Tato metoda je volaná pouze pro elementy s tvarem ElementShapeType == GraphElementShapeType.UserDraw,
        /// anebo pro všechny elementy na řádcích, jejichž GraphMode == RowGraphMode.UserDraw.
        /// Metoda musí element buď plně vykreslit (a nastavit args.IsAllFinished = true), nebo musí do jednotlivých dat argumentu vložit údaje pro vykreslení (to pak zajistí graf sám).
        /// </summary>
        /// <param name="args"></param>
        void DrawElement(GraphElementPainterArgs args);
    }
	#endregion
    #region Delegate, EventArgs
    public delegate void GraphElementHandler(object sender, GraphElementEventArgs args);
    public class GraphElementEventArgs : EventArgs
    {
        internal GraphElementEventArgs(IDataSource dataSource, IDataRow dataRow, IDataElement dataElement)
        {
            this.DataSource = dataSource;
            this.DataRow = dataRow;
            this.DataElement = dataElement;
        }
        public IDataSource DataSource { get; private set; }
        public IDataRow DataRow { get; private set; }
        public IDataElement DataElement { get; private set; }
        /// <summary>
        /// Pokud handler nastaví true, pak sděluje do GUI, že doubleclick řádně zpracoval a GUI se jím dále nemusí zabývat.
        /// Pokud zde zůstane false (defaultní hodnota), pak GUI usoudí, že handler si s událostí nevěděl rady a zachová se k DoubleClicku jako by se handler nevyvolal.
        /// </summary>
        public bool Handled { get; set; }
    }
    #endregion
    #region enums RowGraphMode, RowActionType, ElementActionType, RowProperties, ElementProperties
    /// <summary>
	/// Druh zobrazení grafu
	/// </summary>
	public enum RowGraphMode
	{
		/// <summary>
		/// Graf, jehož elementy se nekreslí, tzv. neviditelný graf.
        /// Využívá se kromě jiného v řádku Temp, který je zobrazen po dobu načítání reálných řádků z datového zdroje.
		/// </summary>
		NoDrawingElements = 1,
		/// <summary>
		/// Všechny elementy tohoto řádku dostává k vykreslení datový zdroj
		/// </summary>
        UserDraw,
		/// <summary>
		/// Gantt diagram, vztahy mezi prvky
		/// </summary>
		SingleTask,
		/// <summary>
		/// Využití kapacit, procentuální využití kapacity v čase
		/// </summary>
		Percentage,
		/// <summary>
		/// Linka, spojující hodnotu v čase, s možným podkreslením barvami
		/// Vývoj zásob, stav paměti, atd.
		/// Automatický focus.
		/// Možnost předvolby "Fixní nula" / "Plovoucí nula".
		/// </summary>
		Line,
		/// <summary>
		/// Vazba mezi úkolem a konkrétní kapacitní jednotkou, pro řetízkový graf s možností přesunů v čase i v místě (nahoru/dolů)
		/// </summary>
		MultiTask,
		/// <summary>
		/// Sloupcový graf, kdy v elementu je deklarovaná výška elementu v IDataElement.ElementHeightRatio
		/// </summary>
		BarGraph
	}
	/// <summary>
	/// Akce po kliknutí / doubleclicku na řádek
	/// </summary>
	public enum RowActionType
	{
		/// <summary>
		/// Řádek nebude provádět žádnou akci
		/// </summary>
		None = 1,
		/// <summary>
		/// Zavolat datový zdroj, sám řekne jaká má být akce
		/// </summary>
		CallDataSourceRequest,
        /// <summary>
        /// Změnit měřítko tak, aby se zobrazil celý element, na který se kliklo.
        /// Tuto hodnotu nemůže mít property ActionOnRowDoubleClick, která definuje akci v případě, že Click byl na řádek, a ne na element.
        /// </summary>
        ZoomTimeToCurrentElements,
		/// <summary>
		/// Změnit měřítko tak, aby se zobrazily všechny elementy načtené do grafu pro aktuální řádek.
		/// </summary>
		ZoomTimeToAllElementsOnRow
	}
    /// <summary>
    /// Akce na konkrétním elementu (lze ji specifikovat pro Click, RightClick, DoubleClick)
    /// </summary>
    public enum ElementActionType
    {
        /// <summary>
        /// Tento element nepředepisuje nic, akce se provede podle defaultu pro řádek
        /// </summary>
        DefaultByRow = 0,
        /// <summary>
        /// V dané situaci má tento element najít nejvhodnější funkci (pomocí Pluginu) a tu má provést.
        /// </summary>
        ExecFunction,
        /// <summary>
        /// V dané situaci má tento element zavolat přímo svůj vlastní handler, který je uložen v odpovídajícím eventu IDataElement.
        /// </summary>
        ExecHandler,
        /// <summary>
        /// V dané situaci má tento element zobrazit kontextové menu.
        /// </summary>
        ContextFunctionMenu
    }
    /// <summary>
    /// Vlastnosti řádku
    /// </summary>
    [Flags]
    public enum RowProperties
    {
        None = 0,
        /// <summary>
        /// Subnody třídit podle klíče. Pokud se třídit nebude, budou subnody vráceny v pořadí zadávání.
        /// </summary>
        ChildSortedKey = 1,
        /// <summary>
        /// Subnody třídit podle textu. Pokud se třídit nebude, budou subnody vráceny v pořadí zadávání.
        /// </summary>
        ChildSortedText = ChildSortedKey << 1,
        /// <summary>
        /// Node má subnody dynamicky načítané: prezentuje se, jako by subnody měl, i v situaci kdy Childs je prázdné
        /// </summary>
        DynamicSubNodeLoading = ChildSortedText << 1,
        /// <summary>
        /// Node má dynamicky načítané elementy. Pokud není zvoleno, pak do vytvářeného řádku vloží své elementy a nastaví AllElementsLoaded.
        /// </summary>
        DynamicElementsLoading = DynamicSubNodeLoading << 1,
        /// <summary>
        /// Node má elementy načítané dynamicky, ale v okamžiku vytváření řádku je vhodné do něj uložit ty elementy, které odpovídají výchozímu času.
        /// Tím se nezruší dynamické donačítání elementů, ale po první dotaz se nevrátí prázdný řádek který si vyžádá další request na elementy.
        /// Do vygenerovaného řádku je třeba vepsat TimeRange, aby graf věděl, že za toto období má elementy načtené a že je již nemusí načítat.
        /// </summary>
        PreLoadingElements = DynamicElementsLoading << 1
    }
    /// <summary>
    /// Vlastnosti elementu
    /// </summary>
    [Flags]
    public enum ElementProperties
    {
        None = 0,
        Selectable = 1
    }
    /// <summary>
	/// Vrstvy grafu
	/// </summary>
	public enum GraphLayerType
	{
        /// <summary>
        /// (1) Pod vrstvou dočasných elementů (ElementTempLayer), úplně vespodu
        /// </summary>
        UnderTempLayer = 1,
        /// <summary>
		/// (2) Dočasná vrstva. leží ještě pod SubLayer, vykresluje se co nejjednodušeji.
		/// </summary>
		ElementTempLayer = 2,
        /// <summary>
        /// (3) Pod vrstvou podkladovou (na ní se kreslí pracovní doba, svátky, atd) (ElementSubLayer), ale nad vrstvou dočasnou (ElementTempLayer)
        /// </summary>
        UnderSubLayer = 3,
		/// <summary>
		/// (4) Podkladová vrstva = zobrazuje typicky pracovní dobu, svátky, směny = data, jimiž nelze z principu hýbat
		/// </summary>
		ElementSubLayer = 4,
        /// <summary>
        /// (5) Pod vrstvou standardních elementů (ElementItemLayer), ale nad podkladovou vrstvou (ElementSubLayer)
        /// </summary>
        UnderItemLayer = 5,
		/// <summary>
		/// (6) Vrstva standardních dat = zobrazuje typicky běžné elementy = data, se kterými uživatel může přijít do styku
		/// </summary>
		ElementItemLayer = 6,
        /// <summary>
        /// (7) Nad vrstvou standardních elementů (ElementItemLayer) = úplně nahoře
        /// </summary>
        AboveItemLayer = 7
	}
    /// <summary>
	/// Stav elementu
	/// </summary>
	public enum GraphElementState
	{
		/// <summary>
		/// Standardní element, který se může stát aktivním
		/// </summary>
		Standart,
		/// <summary>
		/// Element, který je neinteraktivní, mrtvý
		/// </summary>
		Dead,
		/// <summary>
		/// Element, který je vybrán (Kliknutím / rámováním), ale zatím se s ním nehýbe
		/// </summary>
		Selected,
		/// <summary>
		/// Element, kterým se nyní pohybuje (Move / Resize)
		/// </summary>
		Active,
		/// <summary>
		/// Element je v editoru
		/// </summary>
		InEditor,
		/// <summary>
		/// Element, který se nachází pod myší (Hot)
		/// </summary>
		OnMouse
	}
	/// <summary>
	/// Vzhled elementu - jeho tvar
	/// </summary>
	public enum GraphElementShapeType
	{
		/// <summary>
		/// Obdélníkový element grafu = klasika
		/// </summary>
		Rectangle = 1,
		/// <summary>
		/// Obdélníkový element s vyznačením procentuální spotřeby disponibilní kapacity
		/// </summary>
		CapacityUtilization,
		/// <summary>
		/// Prostý šestiúhelník, pro zobrazení operace.
		/// Šestiúhelník je obdobný jako obdélník, ale levá a pravá hrana jsou "zalomené" jako poněkud tupý úhel znaménka &lt; &gt;.
		/// Pokud jsou v datech šestiúhelníku vyplněny datumy, budou vizuálně zvýrazněny odpovídající části.
		/// </summary>
		Hexagon,
		/// <summary>
		/// Trojúhelník doprava, typicky znázorňuje předání dál v konkrétním čase, bez časového úseku.
		/// Pokud je v elementu nenulový čas, je zobrazeno jako pětiúhelník ("prasátko").
		/// </summary>
		RightTriangle,
        /// <summary>
        /// Tvar tohoto elementu vykresluje jeho majitel (v metodě IDataElement.DrawElement())
        /// </summary>
        UserDraw
	}
	/// <summary>
	/// Stav dat, má vliv na ukládání
	/// </summary>
	public enum GraphEditedState
	{
		/// <summary>Nově založená věta, prázdná, neplatná. Bude se Ignorovat..</summary>
		Ignore = 1,
		/// <summary>Nově založená věta, neuložená. Bude se Insertovat.</summary>
		New,
		/// <summary>Věta načtená z databáze, beze změny. Nic se neprovede.</summary>
		Unchanged,
		/// <summary>Věta načtená z databáze, změněná hodnota. Bude se Updatovat.</summary>
		Edited,
		/// <summary>Věta načtená z databáze, určená ke smazání. Bude se Deletovat.</summary>
		Deleted
	}
	#endregion
}
